#include <iostream>
#include "../../region/common/common.h"
#include "../../region/common/controlblock.h"
#include "shared/elements.h"

#include "../../translatetype.h"

#include "shared/members.h"
#include "../expression.h"
#include "shared/shared.h"
#include "../../region/common/heap.h"

Ref translateStaticArrayFromCallable(
    GlobalState* globalState,
    FunctionState* functionState,
    BlockState* blockState,
    LLVMBuilderRef builder,
    StaticArrayFromCallable* staticArrayFromCallable) {

  auto generatorType = staticArrayFromCallable->generatorType;
  auto generatorExpr = staticArrayFromCallable->generatorExpr;
  auto elementType = staticArrayFromCallable->elementType;
  auto arrayRefType = staticArrayFromCallable->arrayRefType;
  auto staticSizedArrayMT = dynamic_cast<StaticSizedArrayT*>(staticArrayFromCallable->arrayRefType->kind);

  auto ssaDefMT = globalState->program->getStaticSizedArray(staticSizedArrayMT);
  auto sizeRef = globalState->constI32(ssaDefMT->size);

  auto arrayRegionInstanceRef =
      // At some point, look up the actual region instance, perhaps from the FunctionState?
      globalState->getRegion(arrayRefType)->createRegionInstanceLocal(functionState, builder);

  auto generatorRef = translateExpression(globalState, functionState, blockState, builder, generatorExpr);
  globalState->getRegion(generatorType)
      ->checkValidReference(FL(), functionState, builder, true, generatorType, generatorRef);

  std::unique_ptr<Ref> result;
  if (staticArrayFromCallable->arrayRefType->location == Location::INLINE) {
//        auto valStructL =
//            globalState->getInnerStruct(structKind->fullName);
//        return constructInnerStruct(
//            builder, structM, valStructL, membersLE);
    { assert(false); throw 1337; }
  } else {
    // If we get here, arrayLT is a pointer to our counted struct.
    auto ssaLiveRef =
        globalState->getRegion(staticArrayFromCallable->arrayRefType)->constructStaticSizedArray(
            makeVoidRef(globalState),
            functionState,
            builder,
            staticArrayFromCallable->arrayRefType,
            staticSizedArrayMT);
    auto ssaRef = toRef(globalState, arrayRefType, ssaLiveRef);

    buildFlare(FL(), globalState, functionState, builder);
    fillStaticSizedArrayFromCallable(
        globalState,
        functionState,
        builder,
        arrayRegionInstanceRef,
        arrayRefType,
        staticSizedArrayMT,
        elementType,
        generatorType,
        staticArrayFromCallable->generatorMethod,
        generatorRef,
        sizeRef,
        ssaLiveRef);//getRuntimeSizedArrayContentsPtr(builder, rsaWrapperPtrLE));
    buildFlare(FL(), globalState, functionState, builder);

    globalState->getRegion(staticArrayFromCallable->arrayRefType)
        ->checkValidReference(FL(), functionState, builder, true, staticArrayFromCallable->arrayRefType, ssaRef);
    result.reset(new Ref(ssaRef));
  }

  globalState->getRegion(generatorType)->dealias(AFL("ConstructRSA"), functionState, builder, generatorType, generatorRef);

  return std::move(*result);
}
